{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "intro",
   "metadata": {},
   "source": [
    "# NumPy随机数与概率分布\n",
    "\n",
    "## 学习目标\n",
    "\n",
    "通过本节课的学习，你将掌握：\n",
    "\n",
    "1. 🎲 **随机数生成**：掌握NumPy中各种随机数生成方法\n",
    "2. 📊 **概率分布**：理解常见概率分布及其应用场景\n",
    "3. 🔄 **随机采样**：学会使用随机抽样和洗牌技术\n",
    "4. 🎯 **实战应用**：掌握蒙特卡洛、随机游走、Bootstrap等经典方法\n",
    "\n",
    "---\n",
    "\n",
    "## 为什么要学习随机数与概率分布？\n",
    "\n",
    "在数据科学和科学计算中，随机数生成和概率分布有着广泛的应用：\n",
    "\n",
    "- **数据模拟**：生成模拟数据进行测试和验证\n",
    "- **蒙特卡洛方法**：通过随机采样求解复杂问题\n",
    "- **机器学习**：数据增强、随机初始化、Dropout等\n",
    "- **统计分析**：Bootstrap重采样、置信区间估计\n",
    "- **金融建模**：股票价格模拟、风险评估\n",
    "\n",
    "NumPy提供了强大的随机数生成功能，支持多种概率分布，是科学计算的重要工具。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "section1",
   "metadata": {},
   "source": [
    "## 1. 随机数生成基础\n",
    "\n",
    "### 1.1 设置随机种子\n",
    "\n",
    "**为什么需要随机种子？**\n",
    "- 计算机生成的是\"伪随机数\"，通过数学算法产生\n",
    "- 设置相同的随机种子可以确保结果可重复\n",
    "- 在科学研究和调试中非常重要"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "seed",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一次生成： [0.37454012 0.95071431 0.73199394 0.59865848 0.15601864]\n",
      "第二次生成（相同种子）： [0.37454012 0.95071431 0.73199394 0.59865848 0.15601864]\n",
      "不设置种子： [0.15599452 0.05808361 0.86617615 0.60111501 0.70807258]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置随机种子\n",
    "np.random.seed(42)  # 使用固定种子，结果可重复\n",
    "\n",
    "# 生成随机数\n",
    "random_numbers = np.random.random(5)\n",
    "print(\"第一次生成：\", random_numbers)\n",
    "\n",
    "# 再次设置相同种子\n",
    "np.random.seed(42)\n",
    "random_numbers = np.random.random(5)\n",
    "print(\"第二次生成（相同种子）：\", random_numbers)\n",
    "\n",
    "# 不设置种子，每次结果不同\n",
    "random_numbers = np.random.random(5)\n",
    "print(\"不设置种子：\", random_numbers)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "basic-random",
   "metadata": {},
   "source": [
    "### 1.2 基本随机数生成方法\n",
    "\n",
    "| 函数 | 功能 | 示例 |\n",
    "|------|------|------|\n",
    "| `random()` | 生成[0,1)均匀分布 | `np.random.random((3,3))` |\n",
    "| `rand()` | 同上，但参数不用元组 | `np.random.rand(3,3)` |\n",
    "| `randn()` | 标准正态分布(μ=0, σ=1) | `np.random.randn(3,3)` |\n",
    "| `randint()` | 随机整数 | `np.random.randint(0,10,(3,3))` |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "basic-methods",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "均匀分布随机数：\n",
      " [[0.02058449 0.96990985 0.83244264]\n",
      " [0.21233911 0.18182497 0.18340451]\n",
      " [0.30424224 0.52475643 0.43194502]]\n",
      "\n",
      "使用rand生成：\n",
      " [[0.29122914 0.61185289 0.13949386]\n",
      " [0.29214465 0.36636184 0.45606998]\n",
      " [0.78517596 0.19967378 0.51423444]]\n",
      "\n",
      "标准正态分布：\n",
      " [[-0.54438272  0.11092259 -1.15099358]\n",
      " [ 0.37569802 -0.60063869 -0.29169375]\n",
      " [-0.60170661  1.85227818 -0.01349722]]\n",
      "\n",
      "随机整数：\n",
      " [[2 0 3]\n",
      " [1 7 3]\n",
      " [1 5 5]]\n"
     ]
    }
   ],
   "source": [
    "# 1. random()：生成[0,1)之间的均匀分布随机数\n",
    "uniform_random = np.random.random((3, 3))\n",
    "print(\"均匀分布随机数：\\n\", uniform_random)\n",
    "\n",
    "# 2. rand()：另一种生成均匀分布的方法\n",
    "uniform_rand = np.random.rand(3, 3)  # 注意：不需要元组\n",
    "print(\"\\n使用rand生成：\\n\", uniform_rand)\n",
    "\n",
    "# 3. randn()：生成标准正态分布（均值0，标准差1）\n",
    "normal_random = np.random.randn(3, 3)\n",
    "print(\"\\n标准正态分布：\\n\", normal_random)\n",
    "\n",
    "# 4. randint()：生成随机整数\n",
    "# 生成[0, 10)之间的随机整数\n",
    "int_random = np.random.randint(0, 10, size=(3, 3))\n",
    "print(\"\\n随机整数：\\n\", int_random)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "distributions",
   "metadata": {},
   "source": [
    "## 2. 常见概率分布\n",
    "\n",
    "### 2.1 均匀分布（Uniform Distribution）\n",
    "\n",
    "**特点**：在指定区间内每个值出现的概率相等  \n",
    "**应用**：随机初始化、模拟骰子、随机选择等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "uniform",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 27010 (\\N{CJK UNIFIED IDEOGRAPH-6982}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 29575 (\\N{CJK UNIFIED IDEOGRAPH-7387}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 23494 (\\N{CJK UNIFIED IDEOGRAPH-5BC6}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 24230 (\\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 22343 (\\N{CJK UNIFIED IDEOGRAPH-5747}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 21248 (\\N{CJK UNIFIED IDEOGRAPH-5300}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 20998 (\\N{CJK UNIFIED IDEOGRAPH-5206}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 24067 (\\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n",
      "/opt/anaconda3/lib/python3.13/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 20540 (\\N{CJK UNIFIED IDEOGRAPH-503C}) missing from font(s) DejaVu Sans.\n",
      "  fig.canvas.print_figure(bytes_io, **kw)\n"
     ]
    },
    {
     "data": {
      "image/png": "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AEiAcAUAAJAA4QoAACABwhUAAEAChCsAAIAECFcAAAAJEK4AAAASIFwBAAAkQLgCAABIgHAFAACQAOEKAAAgAcIVAABAAoQrAACABAhXAAAACRCuAAAAEiBcAQAAJEC4AgAASIBwBQAAkADhCgAAIAF5D1eLFi2KqqqqKCsri+rq6njiiSfedfyqVauiuro6ysrKYvz48bFkyZIuY95888247LLLYtSoUVFWVhYTJkyIFStWHKhNAAAAyG+4Wr58ecyaNSuuueaaWLduXUydOjXOOOOM2Lx5c7fjN27cGGeeeWZMnTo11q1bF1dffXVcfvnl8cADD3SMaW1tjdNOOy1eeeWV+OEPfxjPP/983HXXXXHEEUf01mYBAACHoH75XPltt90WF110UVx88cUREVFbWxs/+9nPYvHixTF//vwu45csWRJjx46N2traiIiYMGFC/OY3v4kFCxbEOeecExERy5Yti9dffz2eeuqp6N+/f0REjBs3rnc2CAAAOGTlLVy1trbGmjVrYs6cOZ2WT5s2LZ566qlua1avXh3Tpk3rtOz000+PpUuXxp49e6J///7xk5/8JCZPnhyXXXZZPPTQQzF8+PA499xz46qrrori4uJub7elpSVaWlo6fm9sbIyIiHQ6Hel0en82MxGZTCZSqVSkUplIpXreTyqViaKiInWHYF0u8yVfvaorjLrefI3Z317VFUZdX3hfysc61e27ri/MGXOtsOpSqVRkMpm8749ns/68hauGhoZob2+PysrKTssrKytj69at3dZs3bq12/FtbW3R0NAQo0aNipdffjl+8YtfxHnnnRcrVqyIF198MS677LJoa2uLb3zjG93e7vz58+OGG27osry+vj52796d4xYmp7m5OUaNqojDDmuO0tJtPa4bMqQ9ioqOiaqqnVFeru7Qqjsi0uldWdXlr1d1hVGX/ZzJdX3736u6wqjrvTljrh0sdYU/Z8y1wqlraWmO8vKKaG5ujm3bsnssktbU1NTjsXk9LTAiIpVKdfp971GabMa/c3k6nY4RI0bEnXfeGcXFxVFdXR2vvfZa3HrrrfsMV3Pnzo2ampqO3xsbG2PMmDExfPjwKC8vz2m7ktTU1BR1dQ1RXz8oBg4c0eO6hobiePbZFyKdHhgVFeoOlbrt24ujqGhLpNMDYtiwntflo1d1hVGX65zJdX37U6uu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fCFb5gzZMmfIljlDtgplzgwZMqRH4/J2QYuSkpKorq6OlStXdlq+cuXKmDJlSrc1kydP7jL+kUceiUmTJkX//v3fdcy+bhMAACAJeT0tsKamJs4///yYNGlSTJ48Oe68887YvHlzzJgxIyLePl1vy5Yt8f3vfz8iImbMmBF33HFH1NTUxCWXXBKrV6+OpUuXxn333ddxm1dccUV8/OMfj5tvvjk+97nPxUMPPRSPPvpoPPnkk3nZRgAA4NCQ13A1ffr02L59e9x4441RV1cXEydOjBUrVsS4ceMiIqKurq7T37yqqqqKFStWxOzZs2PhwoUxevTouP322+Occ87pGDNlypS4//7749prr43rrrsujjrqqFi+fHmcdNJJvb59SSktLY3rr7++y6mL0B3zhWyZM2TLnCFb5gzZ6qtzJpXJ9OSaggAAALybvP4RYQAAgIOFcAUAAJAA4QoAACABwhUAAEAChKsCt2jRoqiqqoqysrKorq6OJ554It8tUaDmz58fH/3oR2Pw4MExYsSIOPvss+P555/Pd1v0IfPnz49UKhWzZs3KdysUsC1btsSXv/zlGDZsWAwcODA+/OEPx5o1a/LdFgWqra0trr322qiqqooBAwbE+PHj48Ybb4x0Op3v1igQjz/+eJx11lkxevToSKVS8eMf/7jT/2cymfjmN78Zo0ePjgEDBsSpp54av/vd7/LTbA8IVwVs+fLlMWvWrLjmmmti3bp1MXXq1DjjjDM6XZ4e9lq1alVcdtll8fTTT8fKlSujra0tpk2bFm+99Va+W6MP+PWvfx133nlnHH/88fluhQL2xhtvxMknnxz9+/ePn/70p/Ff//Vf8Z3vfCeGDh2a79YoUDfffHMsWbIk7rjjjtiwYUPccsstceutt8b/+T//J9+tUSDeeuut+Mu//Mu44447uv3/W265JW677ba444474te//nWMHDkyTjvttGhqaurlTnvGpdgL2EknnRQnnHBCLF68uGPZhAkT4uyzz4758+fnsTP6gvr6+hgxYkSsWrUqPv7xj+e7HQpYc3NznHDCCbFo0aL49re/HR/+8IejtrY2321RgObMmRO//OUvnUVBj33mM5+JysrKWLp0aceyc845JwYOHBj/7//9vzx2RiFKpVLx4IMPxtlnnx0Rbx+1Gj16dMyaNSuuuuqqiIhoaWmJysrKuPnmm+N//+//ncduu+fIVYFqbW2NNWvWxLRp0zotnzZtWjz11FN56oq+ZMeOHRERcfjhh+e5EwrdZZddFp/+9KfjU5/6VL5bocD95Cc/iUmTJsUXvvCFGDFiRHzkIx+Ju+66K99tUcA+9rGPxc9//vN44YUXIiLit7/9bTz55JNx5pln5rkz+oKNGzfG1q1bO+0Pl5aWximnnFKw+8P98t0A3WtoaIj29vaorKzstLyysjK2bt2ap67oKzKZTNTU1MTHPvaxmDhxYr7boYDdf//9sXbt2vj1r3+d71boA15++eVYvHhx1NTUxNVXXx3PPPNMXH755VFaWhoXXHBBvtujAF111VWxY8eOOPbYY6O4uDja29tj3rx58aUvfSnfrdEH7N3n7W5/eNOmTflo6T0JVwUulUp1+j2TyXRZBv/TP/zDP8Szzz4bTz75ZL5boYC9+uqrccUVV8QjjzwSZWVl+W6HPiCdTsekSZPipptuioiIj3zkI/G73/0uFi9eLFzRreXLl8cPfvCDuPfee+NDH/pQrF+/PmbNmhWjR4+Or3zlK/lujz6iL+0PC1cFqqKiIoqLi7scpdq2bVuX9A7v9LWvfS1+8pOfxOOPPx5HHnlkvtuhgK1Zsya2bdsW1dXVHcva29vj8ccfjzvuuCNaWlqiuLg4jx1SaEaNGhXHHXdcp2UTJkyIBx54IE8dUei+/vWvx5w5c+Jv//ZvIyLiL/7iL2LTpk0xf/584Yr3NHLkyIh4+wjWqFGjOpYX8v6w71wVqJKSkqiuro6VK1d2Wr5y5cqYMmVKnrqikGUymfiHf/iH+NGPfhS/+MUvoqqqKt8tUeA++clPxnPPPRfr16/v+Jk0aVKcd955sX79esGKLk4++eQuf+LhhRdeiHHjxuWpIwrdzp07o6io8+5mcXGxS7HTI1VVVTFy5MhO+8Otra2xatWqgt0fduSqgNXU1MT5558fkyZNismTJ8edd94ZmzdvjhkzZuS7NQrQZZddFvfee2889NBDMXjw4I6jnkOGDIkBAwbkuTsK0eDBg7t8J++www6LYcOG+a4e3Zo9e3ZMmTIlbrrppvjiF78YzzzzTNx5551x55135rs1CtRZZ50V8+bNi7Fjx8aHPvShWLduXdx2221x4YUX5rs1CkRzc3O89NJLHb9v3Lgx1q9fH4cffniMHTs2Zs2aFTfddFMcffTRcfTRR8dNN90UAwcOjHPPPTePXe+bS7EXuEWLFsUtt9wSdXV1MXHixPjud7/rstp0a1/nHv/f//t/46tf/WrvNkOfdeqpp7oUO+/q4Ycfjrlz58aLL74YVVVVUVNTE5dcckm+26JANTU1xXXXXRcPPvhgbNu2LUaPHh1f+tKX4hvf+EaUlJTkuz0KwGOPPRaf+MQnuiz/yle+EnfffXdkMpm44YYb4l/+5V/ijTfeiJNOOikWLlxYsB8CClcAAAAJ8J0rAACABAhXAAAACRCuAAAAEiBcAQAAJEC4AgAASIBwBQAAkADhCgAAIAHCFQAAQAL65bsBACgkTz31VMycObPb//tf/+t/xT/90z/1ckcA9BXCFQC8Q2NjY5x99tnxzW9+s9PyV155JebMmZOfpgDoE5wWCAAAkADhCgAAIAHCFQAAQAKEKwAAgAQIVwAAAAkQrgAAABIgXAEAACRAuAIAAEiAcAUAAJAA4QoAACAB/fLdAAAUkiFDhsTDDz8cDz/8cJf/O/300/PQEQB9RSqTyWTy3QQAAEBf57RAAACABAhXAAAACRCuAAAAEiBcAQAAJEC4AgAASIBwBQAAkADhCgAAIAHCFQAAQAKEKwAAgAT8/4TdsvOcV1pzAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "均值：5.003\n",
      "标准差：2.886\n",
      "最小值：0.000\n",
      "最大值：10.000\n"
     ]
    }
   ],
   "source": [
    "# 生成均匀分布\n",
    "# uniform(low, high, size)：生成[low, high)之间的均匀分布\n",
    "uniform_dist = np.random.uniform(0, 10, 1000000)\n",
    "\n",
    "# 可视化\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.hist(uniform_dist, bins=50, density=True, alpha=0.7, color='blue', edgecolor='black')\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # 方案1：推荐\n",
    "plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题\n",
    "\n",
    "plt.xlabel('值')\n",
    "plt.ylabel('概率密度')\n",
    "plt.title('均匀分布 (0, 10)')\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.show()\n",
    "\n",
    "# 统计特征\n",
    "print(f\"均值：{np.mean(uniform_dist):.3f}\")\n",
    "print(f\"标准差：{np.std(uniform_dist):.3f}\")\n",
    "print(f\"最小值：{np.min(uniform_dist):.3f}\")\n",
    "print(f\"最大值：{np.max(uniform_dist):.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "normal",
   "metadata": {},
   "source": [
    "### 2.2 正态分布（Normal Distribution）\n",
    "\n",
    "**特点**：呈钟形曲线，是自然界中最常见的分布  \n",
    "**应用**：测量误差、身高体重、考试成绩、股票收益等  \n",
    "**参数**：均值μ（控制中心位置）、标准差σ（控制离散程度）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "normal-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 生成正态分布\n",
    "# normal(loc=mean, scale=std, size)\n",
    "mean, std = 75, 20  # 均值和标准差\n",
    "normal_dist = np.random.normal(mean, std, 1000000)\n",
    "\n",
    "# 可视化\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.hist(normal_dist, bins=50, density=True, alpha=0.7, color='green', edgecolor='black')\n",
    "\n",
    "# 添加理论正态分布曲线\n",
    "x = np.linspace(mean - 4*std, mean + 4*std, 100)\n",
    "y = (1/np.sqrt(2*np.pi*std**2)) * np.exp(-0.5*((x-mean)/std)**2)\n",
    "plt.plot(x, y, 'r-', linewidth=2, label='理论正态分布')\n",
    "\n",
    "plt.xlabel('值')\n",
    "plt.ylabel('概率密度')\n",
    "plt.title(f'正态分布 (μ={mean}, σ={std})')\n",
    "plt.legend()\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.show()\n",
    "\n",
    "# 统计特征\n",
    "print(f\"均值：{np.mean(normal_dist):.3f}\")\n",
    "print(f\"标准差：{np.std(normal_dist):.3f}\")\n",
    "print(f\"中位数：{np.median(normal_dist):.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "binomial",
   "metadata": {},
   "source": [
    "### 2.3 二项分布（Binomial Distribution）\n",
    "\n",
    "**特点**：描述n次独立试验中成功的次数  \n",
    "**应用**：投硬币、产品质检、A/B测试等  \n",
    "**参数**：n（试验次数）、p（单次成功概率）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "binomial-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文字体（选择其中一个）\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # 方案1：推荐\n",
    "plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题\n",
    "\n",
    "# 生成二项分布\n",
    "# binomial(n, p, size)：n次试验，每次成功概率p\n",
    "n, p = 10, 0.5  # 投掷10次硬币，每次正面朝上概率0.5\n",
    "binomial_dist = np.random.binomial(n, p, 10000)\n",
    "\n",
    "# 可视化\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.hist(binomial_dist, bins=np.arange(0, n+2)-0.5, density=True, \n",
    "         alpha=0.7, color='coral', edgecolor='black')\n",
    "plt.xlabel('成功次数')\n",
    "plt.ylabel('概率')\n",
    "plt.title(f'二项分布 (n={n}, p={p})')\n",
    "plt.xticks(range(0, n+1))\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "poisson",
   "metadata": {},
   "source": [
    "### 2.4 泊松分布（Poisson Distribution）\n",
    "\n",
    "**特点**：描述单位时间内随机事件发生的次数  \n",
    "**应用**：网站访问量、客服电话数、放射性衰变等  \n",
    "**参数**：λ（平均发生率）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "poisson-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "# 生成泊松分布\n",
    "# poisson(lam, size)：lam是单位时间内事件的平均发生率\n",
    "lam = 3  # 平均每小时发生3次\n",
    "poisson_dist = np.random.poisson(lam, 10000)\n",
    "\n",
    "# 可视化\n",
    "plt.figure(figsize=(10, 6))\n",
    "unique_values = np.unique(poisson_dist)\n",
    "counts = np.bincount(poisson_dist)\n",
    "plt.bar(unique_values, counts[unique_values]/10000, alpha=0.7, \n",
    "        color='lightblue', edgecolor='black')\n",
    "plt.xlabel('事件发生次数')\n",
    "plt.ylabel('概率')\n",
    "plt.title(f'泊松分布 (λ={lam})')\n",
    "plt.grid(True, alpha=0.3, axis='y')\n",
    "plt.show()\n",
    "\n",
    "# 输出统计信息\n",
    "print(f\"理论均值：{lam}\")\n",
    "print(f\"实际均值：{np.mean(poisson_dist):.3f}\")\n",
    "print(f\"理论方差：{lam}\")\n",
    "print(f\"实际方差：{np.var(poisson_dist):.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "exponential",
   "metadata": {},
   "source": [
    "### 2.5 指数分布（Exponential Distribution）\n",
    "\n",
    "**特点**：描述独立随机事件发生的时间间隔  \n",
    "**应用**：顾客到达间隔、设备寿命、服务时间等  \n",
    "**参数**：scale = 1/λ（平均时间间隔）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "exponential-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "# 生成指数分布\n",
    "# exponential(scale, size)：scale = 1/λ\n",
    "scale = 2  # 平均时间间隔\n",
    "exponential_dist = np.random.exponential(scale, 100000)\n",
    "\n",
    "# 可视化\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.hist(exponential_dist, bins=50, density=True, alpha=0.7, \n",
    "         color='gold', edgecolor='black', label='实际数据')\n",
    "\n",
    "# 添加理论曲线\n",
    "x = np.linspace(0, 15, 100)\n",
    "y = (1/scale) * np.exp(-x/scale)\n",
    "plt.plot(x, y, 'r-', linewidth=2, label='理论指数分布')\n",
    "\n",
    "plt.xlabel('值')\n",
    "plt.ylabel('概率密度')\n",
    "plt.title(f'指数分布 (scale={scale})')\n",
    "plt.legend()\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.xlim(0, 15)\n",
    "plt.show()\n",
    "\n",
    "# 输出统计信息\n",
    "print(f\"理论均值：{scale}\")\n",
    "print(f\"实际均值：{np.mean(exponential_dist):.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "multivariate",
   "metadata": {},
   "source": [
    "## 3. 多变量分布\n",
    "\n",
    "### 3.1 多变量正态分布\n",
    "\n",
    "**应用**：多个相关变量的联合分布模拟  \n",
    "**参数**：均值向量、协方差矩阵（控制变量间的相关性）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "multivariate-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "# 生成二维正态分布\n",
    "mean = [0, 0]  # 均值向量\n",
    "cov = [[1, 0.5], [0.5, 1]]  # 协方差矩阵\n",
    "\n",
    "# 生成数据\n",
    "multivariate_normal = np.random.multivariate_normal(mean, cov, 1000)\n",
    "\n",
    "# 可视化\n",
    "plt.figure(figsize=(10, 8))\n",
    "plt.scatter(multivariate_normal[:, 0], multivariate_normal[:, 1], \n",
    "           alpha=0.5, color='blue', s=20)\n",
    "plt.xlabel('X1')\n",
    "plt.ylabel('X2')\n",
    "plt.title('二维正态分布')\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.axis('equal')\n",
    "plt.show()\n",
    "\n",
    "# 计算相关系数\n",
    "correlation = np.corrcoef(multivariate_normal[:, 0], multivariate_normal[:, 1])\n",
    "print(f\"相关系数矩阵：\")\n",
    "print(correlation)\n",
    "print(f\"\\nX1与X2的相关系数：{correlation[0, 1]:.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "correlation",
   "metadata": {},
   "source": [
    "### 3.2 不同相关性的二维分布\n",
    "\n",
    "观察不同相关系数对分布形状的影响"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "correlation-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "# 创建不同相关性的二维分布\n",
    "fig, axes = plt.subplots(2, 2, figsize=(12, 10))\n",
    "correlations = [0, 0.5, -0.5, 0.9]\n",
    "mean = [0, 0]\n",
    "\n",
    "for i, corr in enumerate(correlations):\n",
    "    ax = axes[i//2, i%2]\n",
    "    \n",
    "    # 创建协方差矩阵\n",
    "    cov = [[1, corr], [corr, 1]]\n",
    "    \n",
    "    # 生成数据\n",
    "    data = np.random.multivariate_normal(mean, cov, 1000)\n",
    "    \n",
    "    # 绘制散点图\n",
    "    ax.scatter(data[:, 0], data[:, 1], alpha=0.3, s=1)\n",
    "    ax.set_title(f'相关系数 = {corr}')\n",
    "    ax.set_xlabel('X1')\n",
    "    ax.set_ylabel('X2')\n",
    "    ax.grid(True, alpha=0.3)\n",
    "    ax.axis('equal')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sampling",
   "metadata": {},
   "source": [
    "## 4. 随机抽样和洗牌\n",
    "\n",
    "### 4.1 随机抽样\n",
    "\n",
    "**choice()函数**：从给定数组中随机选择元素\n",
    "- 支持有放回/无放回抽样\n",
    "- 支持自定义概率权重"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "sampling-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建样本数据\n",
    "population = np.arange(100)\n",
    "\n",
    "# 1. choice：随机选择\n",
    "# 有放回抽样\n",
    "sample_with_replacement = np.random.choice(population, size=10, replace=True)\n",
    "print(\"有放回抽样：\", sample_with_replacement)\n",
    "\n",
    "# 无放回抽样\n",
    "sample_without_replacement = np.random.choice(population, size=10, replace=False)\n",
    "print(\"无放回抽样：\", sample_without_replacement)\n",
    "\n",
    "# 带概率的抽样\n",
    "# 创建不均匀的概率分布\n",
    "probabilities = np.exp(-0.1 * population)  # 指数衰减的概率\n",
    "probabilities /= probabilities.sum()  # 归一化\n",
    "\n",
    "weighted_sample = np.random.choice(population, size=20, p=probabilities)\n",
    "print(\"加权抽样：\", weighted_sample)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "shuffle",
   "metadata": {},
   "source": [
    "### 4.2 随机排列和洗牌\n",
    "\n",
    "**shuffle() vs permutation()**：\n",
    "- `shuffle()`：原地修改数组（in-place）\n",
    "- `permutation()`：返回新数组，不修改原数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "shuffle-code",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建原始数组\n",
    "original = np.arange(10)\n",
    "print(\"原始数组：\", original)\n",
    "\n",
    "# 1. shuffle：原地洗牌（修改原数组）\n",
    "arr_shuffle = original.copy()\n",
    "np.random.shuffle(arr_shuffle)\n",
    "print(\"shuffle后：\", arr_shuffle)\n",
    "print(\"原数组不变：\", original)\n",
    "\n",
    "# 2. permutation：返回新的打乱顺序的数组\n",
    "arr_permutation = np.random.permutation(original)\n",
    "print(\"permutation结果：\", arr_permutation)\n",
    "\n",
    "# 对二维数组进行行洗牌\n",
    "matrix = np.arange(20).reshape(4, 5)\n",
    "print(\"\\n原始矩阵：\\n\", matrix)\n",
    "\n",
    "# 洗牌行\n",
    "shuffled_matrix = matrix.copy()\n",
    "np.random.shuffle(shuffled_matrix)\n",
    "print(\"按行洗牌后：\\n\", shuffled_matrix)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "case1",
   "metadata": {},
   "source": [
    "## 5. 实际应用案例\n",
    "\n",
    "### 案例1：蒙特卡洛模拟 - 估算π\n",
    "\n",
    "**方法原理**：\n",
    "1. 在正方形内随机撒点\n",
    "2. 统计落在内切圆内的点数\n",
    "3. 利用面积比关系：π/4 ≈ 圆内点数/总点数\n",
    "4. 因此：π ≈ 4 × (圆内点数/总点数)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "monte-carlo",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "def estimate_pi(n_points):\n",
    "    \"\"\"\n",
    "    使用蒙特卡洛方法估算π值\n",
    "    \n",
    "    原理：\n",
    "    1. 在边长为2的正方形内随机生成点（范围：-1到1）\n",
    "    2. 计算每个点到原点的距离\n",
    "    3. 统计落在单位圆（半径=1）内的点数\n",
    "    4. 利用面积比：圆面积/正方形面积 = π*r²/(2r)² = π/4\n",
    "    5. 因此：π ≈ 4 × (圆内点数/总点数)\n",
    "    \"\"\"\n",
    "    # 在单位正方形内生成随机点\n",
    "    points = np.random.uniform(-1, 1, (n_points, 2))\n",
    "    \n",
    "    # 计算每个点到原点的距离\n",
    "    distances = np.sqrt(points[:, 0]**2 + points[:, 1]**2)\n",
    "    \n",
    "    # 统计落在单位圆内的点数\n",
    "    inside_circle = np.sum(distances <= 1)\n",
    "    \n",
    "    # 估算π\n",
    "    pi_estimate = 4 * inside_circle / n_points\n",
    "    \n",
    "    return pi_estimate, points, distances\n",
    "\n",
    "# 使用不同数量的点进行估算\n",
    "print(\"=\" * 60)\n",
    "print(\"蒙特卡洛方法估算π值\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "n_values = [100, 1000, 10000, 100000]\n",
    "for n in n_values:\n",
    "    pi_est, _, _ = estimate_pi(n)\n",
    "    error = abs(pi_est - np.pi)\n",
    "    error_percent = (error / np.pi) * 100\n",
    "    print(f\"样本数 = {n:6d}, π ≈ {pi_est:.6f}, \"\n",
    "          f\"误差 = {error:.6f} ({error_percent:.3f}%)\")\n",
    "\n",
    "print(f\"\\n真实π值 = {np.pi:.6f}\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "# 可视化最后一次模拟\n",
    "pi_est, points, distances = estimate_pi(10000)\n",
    "inside = distances <= 1\n",
    "\n",
    "plt.figure(figsize=(10, 10))\n",
    "plt.scatter(points[inside, 0], points[inside, 1], \n",
    "           c='red', s=1, alpha=0.5, label=f'圆内 ({np.sum(inside)}个点)')\n",
    "plt.scatter(points[~inside, 0], points[~inside, 1], \n",
    "           c='blue', s=1, alpha=0.5, label=f'圆外 ({np.sum(~inside)}个点)')\n",
    "\n",
    "circle = plt.Circle((0, 0), 1, fill=False, color='green', linewidth=2)\n",
    "plt.gca().add_patch(circle)\n",
    "\n",
    "plt.xlim(-1.1, 1.1)\n",
    "plt.ylim(-1.1, 1.1)\n",
    "plt.gca().set_aspect('equal', adjustable='box')\n",
    "plt.title(f'蒙特卡洛方法估算π\\n(样本数=10,000, π≈{pi_est:.6f})', fontsize=14)\n",
    "plt.xlabel('X坐标')\n",
    "plt.ylabel('Y坐标')\n",
    "plt.legend()\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "case2",
   "metadata": {},
   "source": [
    "### 案例2：随机游走模拟\n",
    "\n",
    "**随机游走**：每一步随机向上或向下移动的过程\n",
    "\n",
    "**应用场景**：\n",
    "- 股票价格模拟\n",
    "- 粒子布朗运动\n",
    "- 醉汉走路问题\n",
    "- 生物种群数量变化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "random-walk",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy import stats\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "def random_walk(n_steps, n_walks=1):\n",
    "    \"\"\"\n",
    "    生成随机游走路径\n",
    "    \n",
    "    参数：\n",
    "        n_steps: 总步数\n",
    "        n_walks: 生成多少条随机游走路径\n",
    "    \n",
    "    返回：\n",
    "        walks: 形状为(n_walks, n_steps+1)的数组，每行是一条路径\n",
    "    \"\"\"\n",
    "    # 生成随机步长：每步随机向上(+1)或向下(-1)\n",
    "    steps = np.random.choice([-1, 1], size=(n_walks, n_steps))\n",
    "    \n",
    "    # 计算累积和，得到位置序列\n",
    "    walks = np.concatenate([np.zeros((n_walks, 1)), \n",
    "                           np.cumsum(steps, axis=1)], axis=1)\n",
    "    \n",
    "    return walks\n",
    "\n",
    "# 单条随机游走演示\n",
    "print(\"=\" * 70)\n",
    "print(\"随机游走（Random Walk）模拟\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "n_steps = 1000\n",
    "walk = random_walk(n_steps, n_walks=1)[0]\n",
    "\n",
    "plt.figure(figsize=(12, 6))\n",
    "plt.plot(walk, linewidth=1.5, color='blue', alpha=0.8)\n",
    "plt.axhline(y=0, color='red', linestyle='--', linewidth=1, alpha=0.5, label='起始位置')\n",
    "plt.xlabel('步数')\n",
    "plt.ylabel('位置')\n",
    "plt.title(f'单条随机游走轨迹（共{n_steps}步）', fontsize=14)\n",
    "plt.grid(True, alpha=0.3)\n",
    "plt.legend()\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "print(f\"最终位置: {walk[-1]:.0f}\")\n",
    "print(f\"最大位置: {np.max(walk):.0f}\")\n",
    "print(f\"最小位置: {np.min(walk):.0f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "case3",
   "metadata": {},
   "source": [
    "### 案例3：中心极限定理演示\n",
    "\n",
    "**中心极限定理（CLT）**：无论原始分布是什么形状，当样本量足够大时，样本均值的分布都会趋近于正态分布。\n",
    "\n",
    "**数学表述**：如果 X₁, X₂, ..., Xₙ 是独立同分布的随机变量，均值为μ，方差为σ²，则样本均值 X̄ 的分布趋近于 N(μ, σ²/n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "clt",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy import stats\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "def demonstrate_clt(distribution_func, n_samples, sample_sizes, dist_name):\n",
    "    \"\"\"演示中心极限定理\"\"\"\n",
    "    fig, axes = plt.subplots(2, 3, figsize=(15, 10))\n",
    "    axes = axes.flatten()\n",
    "    \n",
    "    # 第一个子图：显示原始分布\n",
    "    original_data = distribution_func(10000)\n",
    "    axes[0].hist(original_data, bins=50, density=True, alpha=0.7, \n",
    "                 color='skyblue', edgecolor='black')\n",
    "    axes[0].set_title(f'原始分布：{dist_name}', fontsize=12, fontweight='bold')\n",
    "    axes[0].set_xlabel('值')\n",
    "    axes[0].set_ylabel('概率密度')\n",
    "    axes[0].grid(True, alpha=0.3)\n",
    "    \n",
    "    # 对不同的样本大小演示中心极限定理\n",
    "    for idx, n in enumerate(sample_sizes, start=1):\n",
    "        # 生成样本均值\n",
    "        sample_means = [np.mean(distribution_func(n)) for _ in range(n_samples)]\n",
    "        sample_means = np.array(sample_means)\n",
    "        \n",
    "        # 绘制样本均值的分布\n",
    "        axes[idx].hist(sample_means, bins=50, density=True, alpha=0.7,\n",
    "                      color='coral', edgecolor='black', label='样本均值分布')\n",
    "        \n",
    "        # 叠加理论正态分布曲线\n",
    "        mean = np.mean(sample_means)\n",
    "        std = np.std(sample_means)\n",
    "        x = np.linspace(mean - 4*std, mean + 4*std, 100)\n",
    "        y = stats.norm.pdf(x, mean, std)\n",
    "        axes[idx].plot(x, y, 'r-', linewidth=2, label='理论正态分布')\n",
    "        \n",
    "        axes[idx].set_title(f'样本大小 n={n}\\n均值={mean:.3f}, 标准差={std:.3f}', fontsize=11)\n",
    "        axes[idx].set_xlabel('样本均值')\n",
    "        axes[idx].set_ylabel('概率密度')\n",
    "        axes[idx].legend(fontsize=9)\n",
    "        axes[idx].grid(True, alpha=0.3)\n",
    "    \n",
    "    plt.suptitle(f'中心极限定理演示 - {dist_name}分布', fontsize=16, fontweight='bold', y=0.995)\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n",
    "\n",
    "# 演示：均匀分布\n",
    "print(\"中心极限定理演示 - 均匀分布\")\n",
    "demonstrate_clt(\n",
    "    distribution_func=lambda n: np.random.uniform(0, 1, n),\n",
    "    n_samples=10000,\n",
    "    sample_sizes=[2, 5, 10, 30, 100],\n",
    "    dist_name='均匀分布U(0,1)'\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "case4",
   "metadata": {},
   "source": [
    "### 案例4：Bootstrap重采样\n",
    "\n",
    "**Bootstrap方法**：一种统计重采样技术，用于估计统计量的分布和置信区间\n",
    "\n",
    "**核心思想**：\n",
    "1. 从原始样本中有放回地抽取与原样本相同大小的样本\n",
    "2. 计算每个Bootstrap样本的统计量\n",
    "3. 重复上述过程多次（通常1000-10000次）\n",
    "4. 用这些统计量的分布来估计真实分布和置信区间\n",
    "\n",
    "**优点**：\n",
    "- 不需要假设数据的分布（非参数方法）\n",
    "- 适用于复杂的统计量\n",
    "- 当样本量较小或分布未知时特别有用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bootstrap",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "\n",
    "def bootstrap_confidence_interval(data, n_bootstrap=1000, confidence=0.95):\n",
    "    \"\"\"\n",
    "    使用Bootstrap方法计算均值的置信区间\n",
    "    \"\"\"\n",
    "    n = len(data)\n",
    "    bootstrap_means = []\n",
    "    \n",
    "    # 进行Bootstrap重采样\n",
    "    for i in range(n_bootstrap):\n",
    "        bootstrap_sample = np.random.choice(data, size=n, replace=True)\n",
    "        bootstrap_means.append(np.mean(bootstrap_sample))\n",
    "    \n",
    "    bootstrap_means = np.array(bootstrap_means)\n",
    "    \n",
    "    # 计算置信区间（使用百分位数方法）\n",
    "    alpha = 1 - confidence\n",
    "    lower = np.percentile(bootstrap_means, alpha/2 * 100)\n",
    "    upper = np.percentile(bootstrap_means, (1 - alpha/2) * 100)\n",
    "    \n",
    "    return bootstrap_means, (lower, upper)\n",
    "\n",
    "# 生成示例数据（双峰分布）\n",
    "np.random.seed(42)\n",
    "data = np.concatenate([\n",
    "    np.random.normal(100, 10, 300),\n",
    "    np.random.normal(130, 15, 200)\n",
    "])\n",
    "\n",
    "print(\"=\" * 70)\n",
    "print(\"Bootstrap方法演示\")\n",
    "print(\"=\" * 70)\n",
    "print(f\"样本量: {len(data)}\")\n",
    "print(f\"样本均值: {np.mean(data):.2f}\")\n",
    "print(f\"样本标准差: {np.std(data, ddof=1):.2f}\")\n",
    "\n",
    "# 进行Bootstrap分析\n",
    "bootstrap_means, ci = bootstrap_confidence_interval(data, n_bootstrap=1000)\n",
    "\n",
    "print(f\"\\nBootstrap均值的均值: {np.mean(bootstrap_means):.2f}\")\n",
    "print(f\"Bootstrap均值的标准差（标准误）: {np.std(bootstrap_means):.2f}\")\n",
    "print(f\"95%置信区间: [{ci[0]:.2f}, {ci[1]:.2f}]\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "# 可视化\n",
    "fig, axes = plt.subplots(1, 2, figsize=(14, 6))\n",
    "\n",
    "# 左图：原始数据分布\n",
    "axes[0].hist(data, bins=40, density=True, alpha=0.7, \n",
    "            color='skyblue', edgecolor='black')\n",
    "axes[0].axvline(np.mean(data), color='red', linestyle='--', \n",
    "               linewidth=2, label=f'均值: {np.mean(data):.2f}')\n",
    "axes[0].set_xlabel('数据值')\n",
    "axes[0].set_ylabel('概率密度')\n",
    "axes[0].set_title('原始数据分布（双峰分布）', fontsize=13, fontweight='bold')\n",
    "axes[0].legend()\n",
    "axes[0].grid(True, alpha=0.3)\n",
    "\n",
    "# 右图：Bootstrap均值分布\n",
    "axes[1].hist(bootstrap_means, bins=50, density=True, alpha=0.7,\n",
    "            color='lightgreen', edgecolor='black')\n",
    "axes[1].axvline(np.mean(bootstrap_means), color='red', linestyle='--',\n",
    "               linewidth=2, label=f'均值: {np.mean(bootstrap_means):.2f}')\n",
    "axes[1].axvspan(ci[0], ci[1], alpha=0.3, color='orange',\n",
    "               label=f'95% CI: [{ci[0]:.2f}, {ci[1]:.2f}]')\n",
    "axes[1].set_xlabel('Bootstrap均值')\n",
    "axes[1].set_ylabel('概率密度')\n",
    "axes[1].set_title('Bootstrap均值分布（近似正态分布）', fontsize=13, fontweight='bold')\n",
    "axes[1].legend()\n",
    "axes[1].grid(True, alpha=0.3)\n",
    "\n",
    "plt.suptitle('Bootstrap方法：从双峰分布到正态分布', fontsize=15, fontweight='bold', y=1.02)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "summary",
   "metadata": {},
   "source": [
    "## 小结\n",
    "\n",
    "在本节课中，我们学习了：\n",
    "\n",
    "### 1. 随机数生成基础\n",
    "- 随机种子的作用和设置方法\n",
    "- 基本随机数生成函数：`random()`, `rand()`, `randn()`, `randint()`\n",
    "\n",
    "### 2. 常见概率分布\n",
    "| 分布 | 应用场景 | 关键参数 |\n",
    "|------|----------|----------|\n",
    "| 均匀分布 | 随机初始化、模拟骰子 | low, high |\n",
    "| 正态分布 | 测量误差、自然现象 | 均值μ、标准差σ |\n",
    "| 二项分布 | 独立试验、质检 | 试验次数n、成功概率p |\n",
    "| 泊松分布 | 单位时间事件数 | 平均发生率λ |\n",
    "| 指数分布 | 事件间隔时间 | scale=1/λ |\n",
    "\n",
    "### 3. 随机采样技术\n",
    "- `choice()`：随机选择（支持有放回/无放回、加权抽样）\n",
    "- `shuffle()`：原地洗牌\n",
    "- `permutation()`：返回新的随机排列\n",
    "\n",
    "### 4. 实战应用\n",
    "- **蒙特卡洛方法**：通过随机采样求解复杂问题\n",
    "- **随机游走**：模拟股价、粒子运动等随机过程\n",
    "- **中心极限定理**：理解样本均值的分布规律\n",
    "- **Bootstrap重采样**：非参数方法估计置信区间\n",
    "\n",
    "### 关键要点\n",
    "1. 🎲 **可重复性**：使用随机种子确保结果可复现\n",
    "2. 📊 **选对分布**：根据实际问题选择合适的概率分布\n",
    "3. 🔄 **采样技巧**：掌握有放回/无放回、加权抽样等方法\n",
    "4. 🎯 **实战应用**：理解随机方法在实际问题中的应用\n",
    "\n",
    "---\n",
    "\n",
    "## 练习题\n",
    "\n",
    "1. **基础练习**：生成1000个服从正态分布N(100, 15)的随机数，计算其均值和标准差\n",
    "\n",
    "2. **概率分布**：模拟投掷一个不公平的硬币100次（正面概率0.7），统计正面出现的次数\n",
    "\n",
    "3. **蒙特卡洛**：使用蒙特卡洛方法估算圆周率π，尝试不同的样本量（1000, 10000, 100000），观察精度变化\n",
    "\n",
    "4. **随机游走**：生成10条随机游走路径（每条1000步），绘制在同一张图上，观察最终位置的分布\n",
    "\n",
    "5. **Bootstrap应用**：从一组数据中使用Bootstrap方法计算中位数的95%置信区间\n",
    "\n",
    "---\n",
    "\n",
    "## 下一步学习\n",
    "\n",
    "恭喜你完成了NumPy的学习！接下来你可以：\n",
    "\n",
    "- 📊 **Pandas**：学习更高级的数据分析工具\n",
    "- 📈 **Matplotlib/Seaborn**：深入学习数据可视化\n",
    "- 🤖 **Scikit-learn**：开始机器学习之旅\n",
    "- 🔬 **SciPy**：学习更多科学计算方法\n",
    "\n",
    "NumPy是所有这些库的基础，掌握好NumPy将为你的数据科学之路打下坚实的基础！"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
